from Video_Quality_Diagnosis import avg_brightness_gaussian, clearness_detect_ssim, scene_change_detected_init, \
    stripe_interference_fft
from Video_Quality_Diagnosis import video_color_cast, video_contrast_anomaly, video_frame_loss, video_freeze, \
    video_occlusion
from Video_Quality_Diagnosis import video_contrast_anomaly, video_frame_loss, video_freeze, video_occlusion
from Video_Quality_Diagnosis import video_horizontal_stripes_detect_fdm, video_horizontal_waves_detect, \
    video_jitter_lucas
from Video_Quality_Diagnosis import video_scroll_interference_fdm_sd, video_noise
from Video_Quality_Diagnosis import process_of_defective_frame
import cv2
import paramiko
import os
from datetime import datetime
from configs import Box_ip, Box_user, Box_password


# 视频质量诊断系统
class VQD:
    """
    视频质量诊断系统, 用于检测视频质量异常, 并将检测结果插入数据库
        :param data1: 视频流数据
        :param data2: 诊断项及阈值数据
        :param sftp_path: SFTP服务器路径
        :param sftp_server: SFTP服务器地址
        :param sftp_port: SFTP服务器端口
        :param sftp_username: SFTP服务器用户名
        :param sftp_password: SFTP服务器密码
    """

    # 初始化
    def __init__(self, data1, data2, sftp_path, sftp_server, sftp_port, sftp_username, sftp_password):
        """
        初始化视频质量诊断系统
        data= [{'id':'1','name':'1','rtsp':'123'},{'id':'2','name':'2','rtsp':'123'}]
        """
        self.data1 = data1  # 视频流数据
        self.data2 = data2  # 视频流数据
        self.warn_threshold = None  # 报警阈值
        self.prewarn_threshold = None  # 预警阈值
        self.brightness_detection = avg_brightness_gaussian  # 亮度异常检测
        self.clearness_detection = clearness_detect_ssim  # 清晰度异常检测
        self.scene_change_detection = scene_change_detected_init  # 场景变化检测
        self.stripe_interference_detection = stripe_interference_fft  # 条纹干扰检测
        self.color_cast_detection = video_color_cast  # 偏色检测
        self.contrast_anomaly_detection = video_contrast_anomaly  # 对比度异常检测
        self.frame_loss_detection = video_frame_loss  # 视频丢失检测
        self.freeze_detection = video_freeze  # 视频冻结检测
        self.occlusion_detection = video_occlusion  # 视频遮挡检测
        self.horizontal_stripes_detection = video_horizontal_stripes_detect_fdm  # 横波干扰检测
        self.horizontal_waves_detection = video_horizontal_waves_detect  # 横纹干扰检测
        self.jitter_detection = video_jitter_lucas  # 抖动检测
        self.scroll_interference_detection = video_scroll_interference_fdm_sd  # 滚动干扰检测
        self.noise_detection = video_noise  # 噪声检测

        self.process_of_defective_frame = process_of_defective_frame  # 花帧检测
        self.sftp_path = sftp_path  # SFTP服务器路径
        self.sftp_server = sftp_server  # SFTP服务器地址
        self.sftp_port = sftp_port  # SFTP服务器端口
        self.sftp_username = sftp_username  # SFTP服务器用户名
        self.sftp_password = sftp_password  # SFTP服务器密码

    @staticmethod
    def sftp_upload(local_path, filename, sftp_path, sftp_server, sftp_port, sftp_username, sftp_password):
        """
        上传文件到SFTP服务器
        :param local_path: 本地文件路径
        :param filename: 文件名
        """
        # 创建一个SSH客户端对象
        port = 9001
        ssh = paramiko.SSHClient()
        # 允许连接到不在know_hosts文件中的主机（谨慎使用，因为这可能会使你的连接容易受到中间人攻击）
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        # 连接到SFTP服务器
        try:
            # ssh.connect(hostname=sftp_server, port=sftp_port, username=sftp_username, password=sftp_password)
            ssh.connect(hostname=sftp_server, port=sftp_port, username=sftp_username, password=sftp_password)
            # print('连接到SFTP服务器成功')
        except Exception as e1:
            print(f"连接到SFTP服务器失败：{e1}")
        # 使用SSH客户端创建一个SFTP客户端对象
        sftp = ssh.open_sftp()
        remote_folder_1st_level = os.path.dirname(sftp_path)
        try:
            # 创建文件夹
            sftp.mkdir(remote_folder_1st_level)
        except Exception as e2:
            print(f"目录已经存在，无需再次创建，{e2}!")
            pass
        # 将本地图像文件写入到SFTP服务器
        try:
            file_name = os.path.join(sftp_path, filename)
            with sftp.file(file_name, 'wb') as f:
                _, img_data = cv2.imencode('.jpg', cv2.imread(local_path))
                f.write(img_data.tobytes())  # 将图像数据写入到SFTP服务器
                print('上传文件成功')
            # os.remove(local_path)  # 删除本地文件
            return f"http://{sftp_server}:{port}{file_name}"
        except Exception as e:
            print(f"上传文件失败2：{e}")
        # 关闭SFTP和SSH连接
        sftp.close()
        ssh.close()

    # 视频质量诊断
    def detection(self):
        """
        调用各诊断程序进行视频质量诊断
        """
        det_data = []  # 诊断数据
        det_list = []
        for data2 in self.data2:
            det_list.append(data2['name'])
        # print(f"检测项目为{det_list}")
        prewarn_threshold, warn_threshold = [int(self.data2[i]['prewarn_threshold']) for i in range(len(self.data2))], \
                                            [int(self.data2[i]['warn_threshold']) for i in range(len(self.data2))]
        # print(f"监控点的预警阈值为{prewarn_threshold}, 报警阈值为{warn_threshold}")
        for data1 in self.data1:
            diagnosis_data = []
            ref = ''

            video_stream_url = data1['rtsp']  # 视频流地址
            # print(f"{video_stream_urls}")
            ndate = datetime.now()
            cap1 = cv2.VideoCapture(video_stream_url)
            fps = int(cap1.get(cv2.CAP_PROP_FPS))

            if cap1.isOpened():
                # cap = cv2.VideoCapture(video_stream_url)
                # print(cap, prewarn_threshold[13], warn_threshold[13])
                ret, frame = cap1.read()
                # 花帧处理

                ndate = datetime.now()
                # print(ndate.strftime("%Y-%m-%d %H:%M:%S"))
                filename = f"result_{ndate.strftime('%Y%m%d_%H%M%S')}.jpg"
                local_file = os.path.join(os.path.dirname(__file__), filename)
                # print(local_file)
                if ret:
                    cv2.imwrite(local_file, frame)
                    # print(frame.shape)
                # ref = self.sftp_upload(local_file, filename, self.sftp_path, self.sftp_server, self.sftp_port,
                #                        self.sftp_username, self.sftp_password)
                ref = self.sftp_upload(local_file, filename, self.sftp_path, self.sftp_server, self.sftp_port,
                                       self.sftp_username, self.sftp_password)
                diagnosis_data = [
                    self.jitter_detection.run(cap1, fps, prewarn_threshold[0],
                                              warn_threshold[0]) if "视频抖动" in det_list else "未检测",
                    self.stripe_interference_detection.run(cap1, fps, prewarn_threshold[1],
                                                           warn_threshold[1]) if "条纹干扰" in det_list else "未检测",
                    self.frame_loss_detection.run(cap1, fps, prewarn_threshold[2],
                                                  warn_threshold[2]) if "视频丢失" in det_list else "未检测",
                    self.occlusion_detection.run(cap1, fps, prewarn_threshold[3],
                                                 warn_threshold[3]) if "视频遮挡" in det_list else "未检测",
                    self.freeze_detection.run(cap1, fps, prewarn_threshold[4],
                                              warn_threshold[4]) if "视频冻结" in det_list else "未检测",
                    self.brightness_detection.run(cap1, fps, prewarn_threshold[5], warn_threshold[5])[
                        0] if "高亮度" in det_list else "未检测",
                    self.brightness_detection.run(cap1, fps, prewarn_threshold[6], warn_threshold[6])[
                        1] if "低亮度" in det_list else "未检测",
                    self.noise_detection.run(cap1, fps, prewarn_threshold[7],
                                             warn_threshold[7]) if "视频噪声" in det_list else "未检测",
                    self.color_cast_detection.run(cap1, fps, prewarn_threshold[8],
                                                  warn_threshold[8]) if "偏色" in det_list else "未检测",
                    self.clearness_detection.run(cap1, fps, prewarn_threshold[9],
                                                 warn_threshold[9]) if "清晰度" in det_list else "未检测",
                    self.scene_change_detection.run(cap1, fps, prewarn_threshold[10],
                                                    warn_threshold[10]) if "场景变化" in det_list else "未检测",
                    self.contrast_anomaly_detection.run(cap1, fps, prewarn_threshold[11],
                                                        warn_threshold[11]) if "对比度" in det_list else "未检测",
                    self.horizontal_waves_detection.run(cap1, prewarn_threshold[12],
                                                        warn_threshold[12]) if "横纹干扰" in det_list else "未检测",
                    self.scroll_interference_detection.run(cap1, fps, prewarn_threshold[13],
                                                           warn_threshold[13]) if "滚动条纹" in det_list else "未检测",
                    self.horizontal_stripes_detection.run(cap1, fps, prewarn_threshold[14],
                                                          warn_threshold[14]) if "横波干扰" in det_list else "未检测"]
            cap2 = cv2.VideoCapture(video_stream_url)
            if cap2.isOpened():
                diagnosis_data.append(
                    self.process_of_defective_frame.run(cap2, fps, prewarn_threshold[15], warn_threshold[
                        15]) if "花帧检测" in det_list else "未检测")
                # self.process_of_defective_frame.find_glitch(cap, prewarn_threshold[15],warn_threshold[15],) if "花帧检测" in det_list else ""]
                # print(f"监控点{data1['name']}的诊断结果为{diagnosis_data}")
                # res_data = [str(data1["id"])] + [data1["ip"]] + [data1["name"]] + [data1["parent_ip"]] + \
                #            ["很差" if "报警" in diagnosis_data else
                #             "达标" if any(x == "正常" for x in diagnosis_data) and all(x in ["正常", ""] for x in diagnosis_data) else
                #             "一般"] + diagnosis_data
                res_data = [str(data1["id"])] + [data1["ip"]] + [data1["name"]] + [data1["parent_ip"]] + \
                           ["很差" if "报警" in diagnosis_data else
                            "达标" if any(x == "正常" for x in diagnosis_data) and all(
                                x in ["正常", "未检测"] for x in diagnosis_data) else
                            "一般"] + diagnosis_data + [ref]+[data1["parent_name"]]
                det_data.append(res_data)
                # test= self.scroll_interference_detection.run(cap, prewarn_threshold[13],warn_threshold[13])
                # test1=self.scene_change_detection.run(cap, prewarn_threshold[10],warn_threshold[10])
            elif not (cap1.isOpened() and cap2.isOpened()):

                # det_data.append([str(data1["id"])] + [data1["ip"]] + [data1["name"]] + [data1["parent_ip"]] + [
                #     ndate.strftime("%Y-%m-%d %H:%M:%S")] + ["登录失败"] + ["检测失败"] * 15 + [''])
                det_data.append([str(data1["id"])] + [data1["ip"]] + [data1["name"]] + [data1["parent_ip"]] + ["失败"] + [
                    "检测失败"] * 16 + ['']+[data1["parent_name"]])
        return det_data

    # 调用检测函数
    # @staticmethod
    # def run(data1, data2,sftp_path, sftp_server,  sftp_username, sftp_password):
    #     """
    #     调用检测函数
    #     """
    #     vqd = VQD(data1, data2,sftp_path, sftp_server,  sftp_username, sftp_password)  # 创建对象，参数为视频名称
    #     res = vqd.detection()  # 调用检测函数
    #     print("诊断完成！")
    #     return res

    @staticmethod
    def run(data1, data2, sftp_path, sftp_server, sftp_port, sftp_username, sftp_password):
        """
        调用检测函数
        """
        vqd = VQD(data1, data2, sftp_path, sftp_server, sftp_port, sftp_username, sftp_password)  # 创建对象，参数为视频名称
        res = vqd.detection()  # 调用检测函数
        print("诊断完成！")

        # 指定特定的子文件夹路径
        folder = 'Video_Quality_Diagnosis'

        # 获取特定文件夹下的所有文件和文件夹
        files_and_dirs = os.listdir(folder)

        # 遍历文件和文件夹
        for item in files_and_dirs:
            # 检查是否是文件并且文件名以'result_'开头
            if os.path.isfile(os.path.join(folder, item)) and item.startswith('result_'):
                # 构建完整的文件路径
                file_path = os.path.join('.', folder, item)
                # 删除文件
                os.remove(file_path)
                print(f"Deleted: {file_path}")
        return res


if __name__ == "__main__":
    data1 = [{"id": 302, "ip": "192.168.7.40", "name": "Camera 01", "parent_ip": "192.168.7.38",
              "rtsp": "rtsp://admin:Pc@12138@192.168.7.40"},
             {"id": 306, "ip": "192.168.7.31", "name": "北门", "parent_ip": "192.168.7.50",
              "rtsp": "rtsp://admin:Pc@12138@192.168.7.31"}]
    # data1=[{"id": 2, "ip": "192.168.7.30", "name": "北门", "parent_ip": "192.168.7.50",
    #   "rtsp": "rtsp://admin:sxygsj123@192.168.7.50:554/Streaming/Unicast/Channels/101"},
    #  {"id": 3, "ip": "192.168.7.31", "name": "西门", "parent_ip": "192.168.7.50",
    #   "rtsp": "rtsp://admin:sxygsj123@192.168.7.50:554/Streaming/Unicast/Channels/201"},
    #  {"id": 4, "ip": "192.168.7.32", "name": "南门", "parent_ip": "192.168.7.50",
    #   "rtsp": "rtsp://admin:sxygsj123@192.168.7.50:554/Streaming/Unicast/Channels/301"}]
    data2 = [{"id": 1, "name": "视频抖动", "prewarn_threshold": "30", "warn_threshold": "70"},  # 视频抖动
             {"id": 2, "name": "条纹干扰", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 3, "name": "视频丢失", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 4, "name": "视频遮挡", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 5, "name": "视频冻结", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 6, "name": "高亮度", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 7, "name": "低亮度", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 8, "name": "视频噪声", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 9, "name": "偏色", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 10, "name": "清晰度", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 11, "name": "场景变化", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 12, "name": "对比度", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 13, "name": "横纹干扰", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 14, "name": "滚动条纹", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 15, "name": "横波干扰", "prewarn_threshold": "30", "warn_threshold": "70"},
             {"id": 16, "name": "花帧检测", "prewarn_threshold": "90", "warn_threshold": "99"}]

    sftp_path = "/data/vqd_data/"
    sftp_server = Box_ip
    sftp_port = 22
    sftp_username = Box_user
    sftp_password = Box_password
    res = VQD.run(data1, data2, sftp_path, sftp_server, sftp_port, sftp_username, sftp_password)
    print(res)
    # print(datetime.now())